#include "unifiedMathFunctions.hpp"
#include "typeAliases.hpp"
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>

using Catch::Approx;
using namespace hms;

TEST_CASE("unified square function"){
	REQUIRE( square( 1  ) == 1 );
	REQUIRE( square(-1  ) == 1 );
	REQUIRE( square( 2  ) == 4 );
	REQUIRE( square(-2  ) == 4 );
	REQUIRE( square( 1.5) == Approx(2.25) );
	REQUIRE( square(-1.5) == Approx(2.25) );
	REQUIRE( square( Array2s{1, 1.5}).isApprox(Array2s{1, 2.25}) );
	REQUIRE( square(-Array2s{1, 1.5}).isApprox(Array2s{1, 2.25}) );
}

TEST_CASE( "notNegative" ){
	REQUIRE( notNegative(0) );
	REQUIRE( notNegative(.1) );
	REQUIRE( notNegative(-0) );
	REQUIRE( !notNegative(-.1) );

	REQUIRE( notNegative(Array1s{0}) );
	REQUIRE( notNegative(Array1s{-0}) );
	REQUIRE( notNegative(-Array1s{0}) );
	REQUIRE( notNegative(Array2s{0,1}) );
	REQUIRE( !notNegative(Array2s{1,-1}) );
}

TEST_CASE( "nonZero" ){
	REQUIRE( nonZero(hms::epsilon) );
	REQUIRE( nonZero(-hms::epsilon) );
	REQUIRE( !nonZero(0) );
	REQUIRE( !nonZero(-0) );
	REQUIRE( !nonZero(Array1s{0}) );
	REQUIRE( !nonZero(Array1s{-0}) );
	REQUIRE( !nonZero(-Array1s{0}) );
	REQUIRE( nonZero(Array1s{hms::epsilon}) );
	REQUIRE( nonZero(Array1s{-hms::epsilon}) );
	REQUIRE( nonZero(-Array1s{hms::epsilon}) );
	REQUIRE( nonZero(Array2s{1,-1}) );
	REQUIRE( !nonZero(Array2s{1,0}) );
}

TEST_CASE( "unified min and max functions" ){
	SECTION("min"){
		REQUIRE(min(1,2) == std::min(1,2));
		REQUIRE( (
			min(Array2s{1,2}, Array2s{0,3}) == Array2s{1,2}.min(Array2s{0,3})
		).all() );
		REQUIRE( ( min(Array2s{1,2}, 1) == Array2s::Ones() ).all() );
		REQUIRE( ( min(1, Array2s{1,2}) == Array2s::Ones() ).all() );
	}
	SECTION("max"){
		REQUIRE(max(1,2) == std::max(1,2));
		REQUIRE( (
			max(Array2s{1,2}, Array2s{0,3}) == Array2s{1,2}.max(Array2s{0,3})
		).all() );
		REQUIRE( (max(Array2s{1,2}, 1) == Array2s{1,2}).all() );
		REQUIRE( (max(1, Array2s{1,2}) == Array2s{1,2}).all() );
	}
}